﻿using NewLife;
using NewLife.Agent;
using NewLife.Log;
using NewLife.Reflection;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace ServerStart.Common
{
    class MyService:ServiceBase
    {

        const string nginxFileName = "nginx.exe";
        static readonly string RootPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", "").Replace("/", "\\"));
        public MyService()
        {
            ServiceName = "SysStartService";
            DisplayName = "Nginx服务";
            Description = "Nginx代理转发服务！";
        }

        public void Main2()
        {

            if (Host == null)
            {
                if (Runtime.Windows)
                    Host = new WindowsService();
                else
                    Host = new Systemd();
            }

            var service = this;
            service.Log = XTrace.Log;

            // 初始化配置
            var set = NewLife.Agent.Setting.Current;
            if (set.ServiceName.IsNullOrEmpty()) set.ServiceName = service.ServiceName;
            if (set.DisplayName.IsNullOrEmpty()) set.DisplayName = service.DisplayName;
            if (set.Description.IsNullOrEmpty()) set.Description = service.Description;

            // 从程序集构造配置
            var asm = AssemblyX.Entry;
            if (set.ServiceName.IsNullOrEmpty()) set.ServiceName = asm.Name;
            if (set.DisplayName.IsNullOrEmpty()) set.DisplayName = asm.Title;
            if (set.Description.IsNullOrEmpty()) set.Description = asm.Description;

            set.Save();

            // 用配置覆盖
            service.ServiceName = set.ServiceName;
            service.DisplayName = set.DisplayName;
            service.Description = set.Description;
            NewLife.Log.XTrace.WriteLine("服务{0}，显示名:{1},描述：{2}", service.ServiceName, service.DisplayName, service.Description);

        }

        internal void Install()
        {
            var exe = GetExeName();

            // 兼容dotnet
            var args = Environment.GetCommandLineArgs();
            if (args.Length >= 1)
            {
                var fileName = Path.GetFileName(exe);
                if (fileName.EqualIgnoreCase("dotnet", "dotnet.exe"))
                    exe += " " + args[0].GetFullPath();
                else if (fileName.EqualIgnoreCase("mono", "mono.exe", "mono-sgen"))
                    exe = args[0].GetFullPath();
            }

            var bin = $"{exe} -s";

            Host.Install(ServiceName, DisplayName, bin, Description);
        }
        /// <summary>
        /// 卸载
        /// </summary>
        internal void UnInstall()
        {
            var name = ServiceName;
            Host.Remove(name);
        }

        /// <summary>显示状态</summary>
        internal int GetStatus()
        {
            var name = ServiceName;
            if (name != DisplayName)
                Console.WriteLine("服务：{0}({1})", DisplayName, name);
            else
                Console.WriteLine("服务：{0}", name);
            Console.WriteLine("描述：{0}", Description);
            Console.Write("状态：{0} ", Host.GetType().Name);

            if (!Host.IsInstalled(name))
                return 0;// ("未安装");
            else if (Host.IsRunning(name))
                return 1;// ("运行中");
            else
                return 2;// ("未启动");
        }

        internal void Start()
        {
            var name = ServiceName;
            if (!Host.IsRunning(name))
                Host.Start(name);
            else
                Host.Restart(name);
            // 稍微等一下状态刷新
            Thread.Sleep(500);

        }
        internal void Stop()
        {
            var name = ServiceName;
            if (Host.IsRunning(name))
                Host.Stop(name);
            // 稍微等一下状态刷新
            Thread.Sleep(500);
        }

        /// <summary>Exe程序名</summary>
        static String GetExeName()
        {
            var p = Process.GetCurrentProcess();
            var filename = p.MainModule.FileName;
            //filename = Path.GetFileName(filename);
            filename = filename.Replace(".vshost.", ".");

            return filename;
        }
        bool runing = true;
        ServiceManager _Manager=null;
        protected override void StartWork(string reason)
        {
            base.StartWork(reason);

            var set = Setting.Current;
            if (set.Services != null)
            {
                XTrace.WriteLine("Services Length = " + set.Services.Length);
                foreach (var item in set.Services)
                {
                    XTrace.WriteLine("Services {0} {1}", item.FileName, item.Arguments);
                }
            }
            // 应用服务管理
            _Manager = new ServiceManager
            {
                Services = set.Services,

                Log = XTrace.Log,
            };

            _Manager.Start();
            //new Thread(new ThreadStart(() =>
            //{

            //    try
            //    {
            //        runing = true;
            //        while (runing)
            //        {
            //            CheckAndStartServer();
            //            Thread.Sleep(1000);
            //        }
            //    }
            //    catch (Exception ex)
            //    {
            //        NewLife.Log.XTrace.WriteException(ex);
            //    }
            //})).Start();
        }
        protected override void StopWork(string reason)
        {
            try
            {
                runing = false;
                base.StopWork(reason);
                //StopServer();
                if (_Manager != null)
                    _Manager.Stop(reason);
            }
            catch (Exception ex)
            {
                NewLife.Log.XTrace.WriteException(ex);
            }
        }

        private void StopServer()
        {
            try
            {
                string nginxFullPath = Path.Combine(RootPath, nginxFileName);
                string exe = Path.GetFileNameWithoutExtension(nginxFullPath);
                var processes = Process.GetProcessesByName(exe);
                if (processes != null && processes.Length > 0)
                {
                    for (int i = 0; i < processes.Length; i++)
                    {
                        if (processes[i].MainModule.FileName == nginxFullPath)
                        {
                            processes[i].Kill();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                NewLife.Log.XTrace.WriteException(ex);
            }
        }

        Process nginxProcess = null;
        /// <summary>
        /// 检查并启动服务
        /// </summary>
        private void CheckAndStartServer()
        {
            try
            {
                string nginxFullPath = Path.Combine(RootPath, nginxFileName);
                if (File.Exists(nginxFullPath))
                {
                    string exe = Path.GetFileNameWithoutExtension(nginxFullPath);
                    var processes = Process.GetProcessesByName(exe);
                    if (processes != null && processes.Length > 0)
                    {
                        for (int i = 0; i < processes.Length; i++)
                        {
                            if (processes[i].MainModule.FileName == nginxFullPath)
                            {
                                return;
                            }
                        }
                    }
                    ProcessStartInfo processStartInfo = new ProcessStartInfo(nginxFullPath);
                    processStartInfo.WorkingDirectory = RootPath;
                    //processStartInfo.UseShellExecute = true;
                    XTrace.WriteLine("服务启动");
                    nginxProcess = Process.Start(processStartInfo);

                    XTrace.WriteLine("服务停止");
                }
                else
                {
                    XTrace.WriteLine("启动服务失败：" + nginxFullPath);
                }
            }
            catch (Exception ex)
            {
                NewLife.Log.XTrace.WriteException(ex);
            }
        }

    }
}
